﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Chapter09
{
    using System.IO;

    partial class Program
    {
        internal static void Begin(Action action, bool active = false)
        {
            if (active)
            {
                Console.WriteLine("开始演示：");
                action();
                Console.WriteLine("演示完毕：");
                Console.ReadLine();
            }
        }

        internal static void C01()
        {
            int i = 0;
            M();
            M(8, "x");
            M(5, guid: Guid.NewGuid(), dt: DateTime.Now);
            M(i++, i++.ToString(), default(DateTime), new Guid());
            M(s: i++.ToString(), x: i++);
            int j = 5;
            M(x: ref j);
        }

        private static void M(int x = 9, string s = "A", DateTime dt = default(DateTime), Guid guid = new Guid())
        {
            Console.WriteLine("x={0}, s={1}, dt={2}, guid={3}, ", x, s, dt, guid);
        }

        private static void M(ref int x)
        {
            Console.WriteLine("x={0}", x);
        }

        internal static void C02()
        {
            ImplicitlyTypedLocalVariables();
        }

        private static void ImplicitlyTypedLocalVariables()
        {
            var name = "Jeff";
            ShowVariableType(name);
            var x = (Exception)null;
            ShowVariableType(x);
            var numbers = new int[] { 1, 2, 3, 4 };
            var collection = new Dictionary<string, float>() { { ".NET", 4.0f } };
            ShowVariableType(collection);
            foreach (var item in collection)
            {
                ShowVariableType(item);
            }
        }

        private static void ShowVariableType<T>(T t)
        {
            Console.WriteLine(typeof(T));
        }

        internal static void C03()
        {
            {
                int x;
                GetVal(out x);
                Console.WriteLine(x);
                AddVal(ref x);
                Console.WriteLine(x);
            }
            {
                bool noMoreFilesToProcess = true;
                FileStream fs = null;
                StartProcessingFiles(ref fs);
                for (; fs != null; ContinueProcessingFiles(ref fs, ref noMoreFilesToProcess))
                {
                    fs.Read(null, 0, 0);
                    noMoreFilesToProcess = false;
                }
            }
            {
                string s1 = "Jeffrey";
                string s2 = "Richter";
                object o1 = s1, o2 = s2;
                Swap(ref o1, ref o2);
                s1 = (string)o1;
                s2 = (string)o2;
                Console.WriteLine(s1);
                Console.WriteLine(s2);
            }
            {
                SomeType st = null;
                //GetAnObject(out st);
                Console.WriteLine(st.val);
            }
            {
                string s1 = "Jeffrey";
                string s2 = "Richter";
                Swap(ref s1, ref s2);
                Console.WriteLine(s1);
                Console.WriteLine(s2);
            }

        }

        internal static void GetVal(out int v)
        {
            v = 10;
        }

        internal static void AddVal(ref int v)
        {
            v += 10;
        }

        private static void StartProcessingFiles(ref FileStream fs)
        {
            fs = new FileStream(null, FileMode.Open);
        }

        private static void ContinueProcessingFiles(ref FileStream fs, ref bool noMoreFilesToProcess)
        {
            fs.Close();
            if (noMoreFilesToProcess)
                fs = null;
            else
                fs = new FileStream(null, FileMode.Open);
        }

        private static void Swap(ref object a, ref object b)
        {
            object t = b;
            b = a;
            a = t;
        }

        private static void Swap<T>(ref T a, ref T b)
        {
            T t = b;
            b = a;
            a = t;
        }

        private class SomeType
        {
            internal int val;

            internal SomeType()
            {
                val = 0;
            }
        }

        private static void GetAnObject(out object o)
        {
            o = new string('X', 100);
        }

        internal static void C04()
        {
            Console.WriteLine(Add(new int[] { 1, 2, 3, 4, 5 }));
            Console.WriteLine(Add(1, 2, 3, 4, 5));
            Console.WriteLine(Add());
            Console.WriteLine(Add(null));
            DisplayTypes(new object(), new Random(), "Jeff", 5);
        }

        private static int Add(params int[] values)
        {
            int sum = 0;
            if (values != null)
            {
                for (int i = 0; i < values.Length; i++)
                {
                    sum += values[i];
                }
            }
            return sum;
        }

        private static void DisplayTypes(params object[] objects)
        {
            if (objects != null)
            {
                foreach (object o in objects)
                {
                    Console.WriteLine(o.GetType());
                }
            }
        }
    }
}
